package com.haiyi.activiti.engine.framework.activiti.gateway;

import com.haiyi.activiti.engine.model.entity.RuleEngine;
import com.haiyi.activiti.engine.exception.RuleVaildResultException;
import com.haiyi.activiti.engine.framework.activiti.manager.RuleEngineManager;
import com.haiyi.activiti.engine.framework.ruleengine.RuleEngineEnum;
import com.haiyi.activiti.engine.framework.ruleengine.RuleEngineFactory;
import com.haiyi.activiti.engine.framework.ruleengine.Stream;
import org.activiti.bpmn.model.ExclusiveGateway;
import org.activiti.bpmn.model.SequenceFlow;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.impl.bpmn.behavior.ExclusiveGatewayActivityBehavior;
import org.activiti.engine.impl.bpmn.helper.SkipExpressionUtil;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
import org.activiti.engine.impl.util.condition.ConditionUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Iterator;

/**
 * <p> 扩展路由网关规则校验 </p>
 *
 * <pre> Created: 2018/12/7 10:38 </pre>
 *
 * @author hlu
 * @version 1.0
 * @since JDK 1.7
 */
@Component
public class ExclusiveGatewayActivityBehaviorExt extends ExclusiveGatewayActivityBehavior {

    protected static Logger log = LoggerFactory.getLogger(ExclusiveGatewayActivityBehaviorExt.class);


    @Autowired
    private RuleEngineFactory factory;
    @Autowired
    private RuleEngineManager ruleEngineManager;


    @Override
    public void leave(DelegateExecution execution) {
        //例子，如果存在enough参数，表达式为是aaa，为假,表达式如果是bbb,为真
        ExclusiveGateway exclusiveGateway = (ExclusiveGateway) execution.getCurrentFlowElement();
        Iterator<SequenceFlow> sequenceFlowIterator = exclusiveGateway.getOutgoingFlows().iterator();
        SequenceFlow outgoingSequenceFlow = null;
        SequenceFlow defaultSequenceFlow = null;
        String defaultSequenceFlowId = exclusiveGateway.getDefaultFlow();

        while (outgoingSequenceFlow == null && sequenceFlowIterator.hasNext()) {
            SequenceFlow sequenceFlow = sequenceFlowIterator.next();
            final String id = sequenceFlow.getId();
            final RuleEngine ruleEngine = ruleEngineManager.createRuleEngineQuery().iid(id).singleResult();
            String conditionExpression;
            if(ruleEngine!=null) {
                conditionExpression = ruleEngine.getExpression();
            }else{
                conditionExpression = sequenceFlow.getConditionExpression();
            }
            if(StringUtils.isEmpty(conditionExpression)){
                //优先使用数据库配置的表达式，如果如果库没配置，就用在流程图中配置的
                log.info("检测到id={}的规则数据库有配置，优先使用数据配置的规则表达式。",id);
                sequenceFlow.setConditionExpression(conditionExpression);
            }

            log.info("当前表达式是：" + conditionExpression);
            if(ruleEngine==null || RuleEngineEnum.ACTIVITI.getCode().equals(ruleEngine.getLanguage())){
                //使用原生activiti进行校验
                String skipExpressionString = sequenceFlow.getSkipExpression();
                if (!SkipExpressionUtil.isSkipExpressionEnabled(execution, skipExpressionString)) {
                    boolean conditionEvaluatesToTrue = ConditionUtil.hasTrueCondition(sequenceFlow, execution);
                    if (conditionEvaluatesToTrue && (defaultSequenceFlowId == null || !defaultSequenceFlowId.equals(sequenceFlow.getId()))) {
                        if (log.isDebugEnabled()) {
                            log.debug("Sequence flow '{}'selected as outgoing sequence flow.", sequenceFlow.getId());
                        }
                        outgoingSequenceFlow = sequenceFlow;
                    }
                } else if (SkipExpressionUtil.shouldSkipFlowElement(Context.getCommandContext(), execution, skipExpressionString)) {
                    outgoingSequenceFlow = sequenceFlow;
                }

                // Already store it, if we would need it later. Saves one for loop.
                if (defaultSequenceFlowId != null && defaultSequenceFlowId.equals(sequenceFlow.getId())) {
                    defaultSequenceFlow = sequenceFlow;
                }
            }else{
                final Stream stream = factory.getRequestServiceByType(ruleEngine.getLanguage())
                        .execute(ruleEngine, execution.getVariables());
                final Object output = stream.getOutput();
                if(output instanceof Boolean && output!=null){
                   boolean retVal = (boolean) output;
                   if(retVal){
                       outgoingSequenceFlow = sequenceFlow;
                   }
                }else{
                    throw new RuleVaildResultException(stream,"规则引擎的输出值必须是布尔类型！");
                }
            }

            // Already store it, if we would need it later. Saves one for loop.
            if (defaultSequenceFlowId != null && defaultSequenceFlowId.equals(sequenceFlow.getId())) {
                defaultSequenceFlow = sequenceFlow;
            }

        }
        if (outgoingSequenceFlow != null) {
            execution.setCurrentFlowElement(outgoingSequenceFlow);
        } else {
            if (defaultSequenceFlow != null) {
                execution.setCurrentFlowElement(defaultSequenceFlow);
            }
        }
        bpmnActivityBehavior.performDefaultOutgoingBehavior((ExecutionEntity) execution);

    }
}
